home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / GNU / GNUPLOTsrc.lha / readline.c < prev    next >
C/C++ Source or Header  |  1996-01-26  |  24KB  |  1,056 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: readline.c,v 1.57 1995/06/14 12:17:52 drd Exp $";
  3. #endif
  4.  
  5.  
  6. /* GNUPLOT - readline.c */
  7. /*
  8.  * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley
  9.  *
  10.  * Permission to use, copy, and distribute this software and its
  11.  * documentation for any purpose with or without fee is hereby granted, 
  12.  * provided that the above copyright notice appear in all copies and 
  13.  * that both that copyright notice and this permission notice appear 
  14.  * in supporting documentation.
  15.  *
  16.  * Permission to modify the software is granted, but not the right to
  17.  * distribute the modified code.  Modifications are to be distributed 
  18.  * as patches to released version.
  19.  *  
  20.  * This software is provided "as is" without express or implied warranty.
  21.  * 
  22.  *
  23.  * AUTHORS
  24.  *
  25.  *   Original Software:
  26.  *     Tom Tkacik
  27.  *
  28.  *   Msdos port and some enhancements:
  29.  *     Gershon Elber and many others.
  30.  * 
  31.  * There is a mailing list for gnuplot users. Note, however, that the
  32.  * newsgroup 
  33.  *    comp.graphics.gnuplot 
  34.  * is identical to the mailing list (they
  35.  * both carry the same set of messages). We prefer that you read the
  36.  * messages through that newsgroup, to subscribing to the mailing list.
  37.  * (If you can read that newsgroup, and are already on the mailing list,
  38.  * please send a message info-gnuplot-request@dartmouth.edu, asking to be
  39.  * removed from the mailing list.)
  40.  *
  41.  * The address for mailing to list members is
  42.  *       info-gnuplot@dartmouth.edu
  43.  * and for mailing administrative requests is 
  44.  *       info-gnuplot-request@dartmouth.edu
  45.  * The mailing list for bug reports is 
  46.  *       bug-gnuplot@dartmouth.edu
  47.  * The list of those interested in beta-test versions is
  48.  *       info-gnuplot-beta@dartmouth.edu
  49.  */
  50.  
  51. #if defined(READLINE) && !defined(GNU_READLINE)
  52.  
  53. #ifdef _WINDOWS
  54. #define _Windows
  55. #endif
  56.  
  57.  
  58. /* a small portable version of GNU's readline */
  59. /* this is not the BASH or GNU EMACS version of READLINE due to Copyleft 
  60.     restrictions */
  61. /* do not need any terminal capabilities except backspace, */
  62. /* and space overwrites a character */
  63.  
  64. /* NANO-EMACS line editing facility */
  65. /* printable characters print as themselves (insert not overwrite) */
  66. /* ^A moves to the beginning of the line */
  67. /* ^B moves back a single character */
  68. /* ^E moves to the end of the line */
  69. /* ^F moves forward a single character */
  70. /* ^K kills from current position to the end of line */
  71. /* ^P moves back through history */
  72. /* ^N moves forward through history */
  73. /* ^H and DEL delete the previous character */
  74. /* ^D deletes the current character, or EOF if line is empty */
  75. /* ^L/^R redraw line in case it gets trashed */
  76. /* ^U kills the entire line */
  77. /* ^W kills last word */
  78. /* LF and CR return the entire line regardless of the cursor postition */
  79. /* EOF with an empty line returns (char *)NULL */
  80.  
  81. /* all other characters are ignored */
  82.  
  83. #include <ctype.h>
  84. #include <signal.h>
  85. #include "plot.h" /* get prototype for alloc and gpfaralloc */
  86. #include "stdfn.h"
  87.  
  88. #if !defined(MSDOS) && !defined(ATARI) && !defined(MTOS) && !defined(_Windows) && !defined(DOS386) && !defined(OSK)
  89.  
  90. /*
  91.  * Set up structures using the proper include file
  92.  */
  93. #if defined(_IBMR2) || defined(alliant)
  94. #define SGTTY
  95. #endif
  96.  
  97. /*  submitted by Francois.Dagorn@cicb.fr */
  98. #ifdef SGTTY
  99. #include <sgtty.h>
  100. static struct sgttyb orig_termio, rl_termio;
  101. /* define terminal control characters */
  102. static struct tchars s_tchars;
  103. #ifndef VERASE
  104. #define VERASE    0
  105. #endif
  106. #ifndef VEOF
  107. #define VEOF      1
  108. #endif
  109. #ifndef VKILL
  110. #define VKILL     2
  111. #endif
  112. #ifdef TIOCGLTC         /* available only with the 'new' line discipline */
  113. static struct ltchars s_ltchars;
  114. #ifndef VWERASE
  115. #define VWERASE   3
  116. #endif
  117. #ifndef VREPRINT
  118. #define VREPRINT  4
  119. #endif
  120. #ifndef VSUSP
  121. #define VSUSP     5
  122. #endif
  123. #endif /* TIOCGLTC */
  124. #ifndef NCCS
  125. #define NCCS      6
  126. #endif
  127.  
  128. #else /* SGTTY */
  129.  
  130. /* SIGTSTP defines job control */
  131. /* if there is job control then we need termios.h instead of termio.h */
  132. /* (Are there any systems with job control that use termio.h?  I hope not.) */
  133. #if defined(SIGTSTP) || defined(TERMIOS)
  134. #ifndef TERMIOS
  135. #define TERMIOS
  136. #endif
  137. #include <termios.h>
  138. /* Added by Robert Eckardt, RobertE@beta.TP2.Ruhr-Uni-Bochum.de */
  139. #ifdef ISC22
  140. #ifndef ONOCR            /* taken from sys/termio.h */
  141. #define ONOCR 0000020    /* true at least for ISC 2.2 */
  142. #endif 
  143. #ifndef IUCLC
  144. #define IUCLC 0001000
  145. #endif
  146. #endif /* ISC22 */
  147. #if defined(NEXT) && !defined(IUCLC)
  148. #define IUCLC 0 /* no idea what this flag does */
  149. #endif
  150.  
  151. static struct termios orig_termio, rl_termio;
  152. #else
  153. #include <termio.h>
  154. static struct termio orig_termio, rl_termio;
  155. /* termio defines NCC instead of NCCS */
  156. #define NCCS    NCC
  157. #endif /* SIGTSTP */
  158. #endif /* SGTTY */
  159.  
  160. /* ULTRIX defines VRPRNT instead of VREPRINT */
  161. #if defined(VRPRNT) && !defined(VREPRINT)
  162. #define VREPRINT VRPRNT
  163. #endif
  164.  
  165. /* define characters to use with our input character handler */
  166. static char term_chars[NCCS];
  167.  
  168. static int term_set = 0;    /* =1 if rl_termio set */
  169.  
  170. #define special_getc() ansi_getc()
  171. static int ansi_getc();
  172.  
  173. #else /* !MSDOS && !ATARI && !_Windows */
  174.  
  175. #ifdef _Windows
  176. #include <windows.h>
  177. #include "win/wtext.h"
  178. #include "win/wgnuplib.h"
  179. extern TW textwin;
  180. #define TEXTUSER 0xf1
  181. #define TEXTGNUPLOT 0xf0
  182. #define special_getc() msdos_getch()
  183. static char msdos_getch();
  184. #endif
  185.  
  186. #if defined(MSDOS) || defined(DOS386)
  187. /* MSDOS specific stuff */
  188. #ifdef DJGPP
  189. #include <pc.h>
  190. #endif
  191. #ifdef __EMX__
  192. #include <conio.h>
  193. #endif
  194. #define special_getc() msdos_getch()
  195. static char msdos_getch();
  196. #endif /* MSDOS */
  197.  
  198. #ifdef OSK
  199. #include <sgstat.h>
  200. #include <modes.h>
  201.  
  202. #define STDIN    0
  203. static int term_set = 0;    /* =1 if new_settings is set */
  204.  
  205. static struct _sgs old_settings;  /* old terminal settings        */
  206. static struct _sgs new_settings;  /* new terminal settings        */
  207.  
  208. #define special_getc() ansi_getc()
  209. static int ansi_getc();
  210.  
  211. /* On OS9 a '\n' is a character 13 and '\r' == '\n'. This gives troubles
  212.    here, so we need a new putc wich handles this correctly and print a
  213.    character 10 on each place we want a '\n'.
  214. */
  215. #undef putc        /* Undefine the macro for putc */
  216.  
  217. static int putc (c,fp)
  218.     char c;
  219.     FILE *fp;
  220. {
  221.     write (fileno(fp), &c, 1);
  222.     if (c == '\012')            /* A normal ASCII '\n' */
  223.     {
  224.         c = '\r';
  225.         write (fileno(fp), &c, 1);
  226.     }
  227. }
  228.  
  229. #endif /* OSK */
  230.  
  231. #if defined(ATARI) || defined(MTOS)
  232. #ifdef __PUREC__
  233. #include <tos.h>
  234. #else
  235. #include <osbind.h>
  236. #endif
  237. #define special_getc() tos_getch()
  238. char tos_getch();
  239. #endif
  240.  
  241. #endif /* !MSDOS && !ATARI && !MTOS && !_Windows && !OSK*/
  242.  
  243. #ifdef OS2
  244. #define special_getc() msdos_getch()
  245. static char msdos_getch();
  246. #endif
  247.  
  248.  
  249. #define MAXBUF    1024    /* initial size and increment of input line length */
  250. #define BACKSPACE 0x08    /* ^H */
  251. #define SPACE    ' '
  252. #ifdef OSK
  253. #define NEWLINE    '\012'
  254. #else
  255. #define NEWLINE    '\n'
  256. #endif
  257.  
  258. struct hist {
  259.     char *line;
  260.     struct hist *prev;
  261.     struct hist *next;
  262. };
  263.  
  264. static struct hist *history = NULL;  /* no history yet */
  265. static struct hist *cur_entry = NULL;
  266.  
  267. static char *cur_line;  /* current contents of the line */
  268. static int line_len=0;
  269. static int cur_pos = 0;    /* current position of the cursor */
  270. static int max_pos = 0;    /* maximum character position */
  271.  
  272.  
  273. static void fix_line __P((void));
  274. static void redraw_line __P((char *prompt));
  275. static void clear_line __P((char *prompt));
  276. static void clear_eoline __P((void));
  277. static void copy_line __P((char *line));
  278. static void set_termio __P((void));
  279. static void reset_termio __P((void));
  280. static int ansi_getc __P((void));
  281. static int user_putc __P((int ch));
  282. static int user_puts __P((char *str));
  283. static void backspace __P((void));
  284. static void extend_cur_line __P((void));
  285.  
  286. /* user_putc and user_puts should be used in the place of
  287.  * fputc(ch,stderr) and fputs(str,stderr) for all output
  288.  * of user typed characters.  This allows MS-Windows to 
  289.  * display user input in a different color. */
  290. static int
  291. user_putc(ch)
  292. int ch;
  293. {
  294.     int rv;
  295. #ifdef _Windows
  296.     TextAttr(&textwin,TEXTUSER);
  297. #endif
  298.     rv = fputc(ch, stderr);
  299. #ifdef _Windows
  300.     TextAttr(&textwin,TEXTGNUPLOT);
  301. #endif
  302.     return rv;
  303. }
  304.  
  305. static int
  306. user_puts(str)
  307. char *str;
  308. {
  309.     int rv;
  310. #ifdef _Windows
  311.     TextAttr(&textwin,TEXTUSER);
  312. #endif
  313.     rv = fputs(str, stderr);
  314. #ifdef _Windows
  315.     TextAttr(&textwin,TEXTGNUPLOT);
  316. #endif
  317.     return rv;
  318. }
  319.  
  320. /* This function provides a centralized non-destructive backspace capability */
  321. /* M. Castro */
  322.  
  323. static void
  324. backspace()
  325. {
  326.     user_putc(BACKSPACE);
  327. }
  328.  
  329. static void extend_cur_line()
  330. {
  331.   char *new_line;
  332.  
  333.   /* extent input line length */
  334.   new_line=ralloc(cur_line, line_len+MAXBUF, NULL);
  335.   if(!new_line) {
  336.     reset_termio();
  337.     int_error("Can't extend readline length", NO_CARET);
  338.   }
  339.   cur_line=new_line;
  340.   line_len+=MAXBUF;
  341. #ifdef DEBUG_STR
  342.   fprintf(stderr, "\nextending readline length to %d chars\n", line_len);
  343. #endif
  344. }
  345.  
  346. char *
  347. readline(prompt)
  348. char *prompt;
  349. {
  350.  
  351.     int cur_char;
  352.     char *new_line;
  353.  
  354.     /* start with a string of MAXBUF chars */
  355.     
  356.     if(line_len!=0) {
  357.         free(cur_line);
  358.         line_len=0;
  359.     }
  360.  
  361.     cur_line=alloc((unsigned long)MAXBUF, "readline");
  362.     line_len=MAXBUF;
  363.  
  364.     /* set the termio so we can do our own input processing */
  365.     set_termio();
  366.  
  367.     /* print the prompt */
  368.     fputs(prompt, stderr);
  369.     cur_line[0] = '\0';
  370.     cur_pos = 0;
  371.     max_pos = 0;
  372.     cur_entry = NULL;
  373.  
  374.     /* get characters */
  375.     for(;;) {
  376.         cur_char = special_getc();
  377.  
  378. /*
  379.  * The #define CHARSET7BIT should be used when one encounters problems with
  380.  * 8bit characters that should not be entered on the commandline. I cannot
  381.  * think on any reasonable example where this could happen, but what do I know?
  382.  * After all, the unix world still ignores 8bit chars in most applications.
  383.  *
  384.  * Note that latin1 defines the chars 0x80-0x9f as control chars. For the
  385.  * benefit of Atari, MSDOS, Windows and NeXT I have decided to ignore this,
  386.  * since it would require more #ifs.
  387.  *
  388.  */
  389.  
  390. #ifdef CHARSET7BIT
  391.         if(isprint(cur_char)) {
  392. #else  /* CHARSET7BIT */
  393.         if(isprint(cur_char) || (((unsigned char)cur_char > 0x7f) &&
  394.                      cur_char != EOF)) {
  395. #endif /* CHARSET7BIT */
  396.             int i;
  397.  
  398.             if(max_pos+1>=line_len) {
  399.                 extend_cur_line();
  400.             }
  401.  
  402.             for(i=max_pos; i>cur_pos; i--) {
  403.                 cur_line[i] = cur_line[i-1];
  404.             }
  405.             user_putc(cur_char);
  406.             cur_line[cur_pos] = cur_char;
  407.             cur_pos += 1;
  408.             max_pos += 1;
  409.             if (cur_pos < max_pos)
  410.                 fix_line();
  411.             cur_line[max_pos] = '\0';
  412.  
  413.         /* else interpret unix terminal driver characters */
  414. #ifdef VERASE
  415.         } else if(cur_char == term_chars[VERASE] ){  /* DEL? */
  416.             if(cur_pos > 0) {
  417.                 int i;
  418.                 cur_pos -= 1;
  419.                 backspace();
  420.                 for(i=cur_pos; i<max_pos; i++)
  421.                     cur_line[i] = cur_line[i+1];
  422.                 max_pos -= 1;
  423.                 fix_line();
  424.             }
  425. #endif /* VERASE */
  426. #ifdef VEOF
  427.         } else if(cur_char == term_chars[VEOF] ){   /* ^D? */
  428.             if(max_pos == 0) {
  429.                 reset_termio();
  430.                 return((char *)NULL);
  431.             }
  432.             if((cur_pos < max_pos)&&(cur_char == 004)) { /* ^D */
  433.                 int i;
  434.                 for(i=cur_pos; i<max_pos; i++)
  435.                     cur_line[i] = cur_line[i+1];
  436.                 max_pos -= 1;
  437.                 fix_line();
  438.             }
  439. #endif /* VEOF */
  440. #ifdef VKILL
  441.         } else if(cur_char == term_chars[VKILL] ){  /* ^U? */
  442.             clear_line(prompt);
  443. #endif /* VKILL */
  444. #ifdef VWERASE
  445.         } else if(cur_char == term_chars[VWERASE] ){  /* ^W? */
  446.             while((cur_pos > 0) &&
  447.                   (cur_line[cur_pos-1] == SPACE)) {
  448.                 cur_pos -= 1;
  449.                 backspace();
  450.             }
  451.             while((cur_pos > 0) &&
  452.                   (cur_line[cur_pos-1] != SPACE)) {
  453.                 cur_pos -= 1;
  454.                 backspace();
  455.             }
  456.             clear_eoline();
  457.             max_pos = cur_pos;
  458. #endif /* VWERASE */
  459. #ifdef VREPRINT
  460.         } else if(cur_char == term_chars[VREPRINT] ){  /* ^R? */
  461.             putc(NEWLINE,stderr); /* go to a fresh line */
  462.             redraw_line(prompt);
  463. #endif /* VREPRINT */
  464. #ifdef VSUSP
  465.         } else if(cur_char == term_chars[VSUSP]) {
  466.             reset_termio();
  467.             kill(0, SIGTSTP);
  468.  
  469.             /* process stops here */
  470.  
  471.             set_termio();
  472.             /* print the prompt */
  473.             redraw_line(prompt);
  474. #endif /* VSUSP */
  475.         } else {
  476.             /* do normal editing commands */
  477.             /* some of these are also done above */
  478.             int i;
  479.             switch(cur_char) {
  480.                 case EOF:
  481.                 reset_termio();
  482.                 return((char *)NULL);
  483.                 case 001: /* ^A */
  484.                 while(cur_pos > 0) {
  485.                     cur_pos -= 1;
  486.                     backspace();
  487.                 }
  488.                 break;
  489.                 case 002: /* ^B */
  490.                 if(cur_pos > 0) {
  491.                     cur_pos -= 1;
  492.                     backspace();
  493.                 }
  494.                 break;
  495.                 case 005: /* ^E */
  496.                 while(cur_pos < max_pos) {
  497.                     user_putc(cur_line[cur_pos]);
  498.                     cur_pos += 1;
  499.                 }
  500.                 break;
  501.                 case 006: /* ^F */
  502.                 if(cur_pos < max_pos) {
  503.                     user_putc(cur_line[cur_pos]);
  504.                     cur_pos += 1;
  505.                 }
  506.                 break;
  507.                 case 013: /* ^K */
  508.                 clear_eoline();
  509.                 max_pos = cur_pos;
  510.                 break;
  511.                 case 020: /* ^P */
  512.                 if(history != NULL) {
  513.                     if(cur_entry == NULL) {
  514.                         cur_entry = history;
  515.                         clear_line(prompt);
  516.                         copy_line(cur_entry->line);
  517.                     } else if(cur_entry->prev != NULL) {
  518.                         cur_entry = cur_entry->prev;
  519.                         clear_line(prompt);
  520.                         copy_line(cur_entry->line);
  521.                     }
  522.                 }
  523.                 break;
  524.                 case 016: /* ^N */
  525.                 if(cur_entry != NULL) {
  526.                     cur_entry = cur_entry->next;
  527.                     clear_line(prompt);
  528.                     if(cur_entry != NULL) 
  529.                         copy_line(cur_entry->line);
  530.                     else
  531.                         cur_pos = max_pos = 0;
  532.                 }
  533.                 break;
  534.                 case 014: /* ^L */
  535.                 case 022: /* ^R */
  536.                 putc(NEWLINE,stderr); /* go to a fresh line */
  537.                 redraw_line(prompt);
  538.                 break;
  539.                 case 0177: /* DEL */
  540.                 case 010: /* ^H */
  541.                 if(cur_pos > 0) {
  542.                     cur_pos -= 1;
  543.                     backspace();
  544.                     for(i=cur_pos; i<max_pos; i++)
  545.                         cur_line[i] = cur_line[i+1];
  546.                     max_pos -= 1;
  547.                     fix_line();
  548.                 }
  549.                 break;
  550.                 case 004: /* ^D */
  551.                 if(max_pos == 0) {
  552.                     reset_termio();
  553.                     return((char *)NULL);
  554.                 }
  555.                 if(cur_pos < max_pos) {
  556.                     for(i=cur_pos; i<max_pos; i++)
  557.                         cur_line[i] = cur_line[i+1];
  558.                     max_pos -= 1;
  559.                     fix_line();
  560.                 }
  561.                 break;
  562.                 case 025:  /* ^U */
  563.                 clear_line(prompt);
  564.                 break;
  565.                 case 027:  /* ^W */
  566.                 while((cur_pos > 0) &&
  567.                       (cur_line[cur_pos-1] == SPACE)) {
  568.                     cur_pos -= 1;
  569.                     backspace();
  570.                 }
  571.                 while((cur_pos > 0) &&
  572.                       (cur_line[cur_pos-1] != SPACE)) {
  573.                     cur_pos -= 1;
  574.                     backspace();
  575.                 }
  576.                 clear_eoline();
  577.                 max_pos = cur_pos;
  578.                 break;
  579.                 case '\n': /* ^J */
  580. #ifndef OSK
  581.                 case '\r': /* ^M */
  582. #endif
  583.                 cur_line[max_pos+1] = '\0';
  584.                 putc(NEWLINE, stderr);
  585.                 new_line = (char *)ralloc(cur_line, (unsigned long)(strlen(cur_line)+1), "line resize");
  586.                 line_len=0;
  587. #ifdef DEBUG_STR
  588.                 fprintf(stderr, "Resizing input line to %d chars\n", strlen(new_line));
  589. #endif
  590.                 reset_termio();
  591.                 return(new_line);
  592.                 default:
  593.                 break;
  594.             }
  595.         }
  596.     }
  597. }
  598.  
  599. /* fix up the line from cur_pos to max_pos */
  600. /* do not need any terminal capabilities except backspace, */
  601. /* and space overwrites a character */
  602. static void
  603. fix_line()
  604. {
  605.     int i;
  606.  
  607.     /* write tail of string */
  608.     for(i=cur_pos; i<max_pos; i++)
  609.         user_putc(cur_line[i]);
  610.  
  611.     /* write a space at the end of the line in case we deleted one */
  612.     user_putc(SPACE);
  613.  
  614.     /* backup to original position */
  615.     for(i=max_pos+1; i>cur_pos; i--)
  616.         backspace();
  617.  
  618. }
  619.  
  620. /* redraw the entire line, putting the cursor where it belongs */
  621. static void
  622. redraw_line(prompt)
  623. char *prompt;
  624. {
  625.     int i;
  626.  
  627.     fputs(prompt, stderr);
  628.     user_puts(cur_line);
  629.  
  630.     /* put the cursor where it belongs */
  631.     for(i=max_pos; i>cur_pos; i--)
  632.         backspace();
  633. }
  634.  
  635. /* clear cur_line and the screen line */
  636. static void
  637. clear_line(prompt)
  638. char *prompt;
  639. {
  640.     int i;
  641.     for(i=0; i<max_pos; i++)
  642.         cur_line[i] = '\0';
  643.  
  644.     for(i=cur_pos; i>0; i--)
  645.         backspace();
  646.  
  647.     for(i=0; i<max_pos; i++)
  648.         putc(SPACE, stderr);
  649.  
  650.     putc('\r', stderr);
  651.     fputs(prompt, stderr);
  652.  
  653.     cur_pos = 0;
  654.     max_pos = 0;
  655. }
  656.  
  657. /* clear to end of line and the screen end of line */
  658. static void
  659. clear_eoline()
  660. {
  661.     int i;
  662.     for(i=cur_pos; i<max_pos; i++)
  663.         cur_line[i] = '\0';
  664.  
  665.     for(i=cur_pos; i<max_pos; i++)
  666.         putc(SPACE, stderr);
  667.     for(i=cur_pos; i<max_pos; i++)
  668.         backspace();
  669. }
  670.  
  671. /* copy line to cur_line, draw it and set cur_pos and max_pos */
  672. static void
  673. copy_line(line)
  674. char *line;
  675. {
  676.     while(strlen(line)+1>line_len) {
  677.         extend_cur_line();
  678.     }
  679.     strcpy(cur_line, line);
  680.     user_puts(cur_line);
  681.     cur_pos = max_pos = strlen(cur_line);
  682. }
  683.  
  684. /* add line to the history */
  685. void
  686. add_history(line)
  687. char *line;
  688. {
  689.     struct hist *entry;
  690.     entry = (struct hist *)alloc((unsigned long)sizeof(struct hist),"history");
  691.     entry->line = alloc((unsigned long)(strlen(line)+1),"history");
  692.     strcpy(entry->line, line);
  693.  
  694.     entry->prev = history;
  695.     entry->next = NULL;
  696.     if(history != NULL) {
  697.         history->next = entry;
  698.     }
  699.     history = entry;
  700. }
  701.  
  702.  
  703. /* Convert ANSI arrow keys to control characters */
  704. static int
  705. ansi_getc()
  706. {
  707.   int c = getc(stdin);
  708.   if (c == 033) {
  709.     c = getc(stdin); /* check for CSI */
  710.     if (c == '[') {
  711.       c = getc(stdin); /* get command character */
  712.       switch (c) {
  713.       case 'D': /* left arrow key */
  714.     c = 002;
  715.     break;
  716.       case 'C': /* right arrow key */
  717.     c = 006;
  718.     break;
  719.       case 'A': /* up arrow key */
  720.     c = 020;
  721.     break;
  722.       case 'B': /* down arrow key */
  723.     c = 016;
  724.     break;
  725.       }
  726.     }
  727.   }
  728.   return c;
  729. }
  730.  
  731. #if defined(MSDOS) || defined(_Windows) || defined(DOS386) || defined(OS2)
  732.  
  733. /* Convert Arrow keystrokes to Control characters: */
  734. static  char
  735. msdos_getch()
  736. {
  737. #ifdef DJGPP
  738.     char c;
  739.     int ch = getkey();
  740.     c = (ch & 0xff00) ? 0 : ch & 0xff;
  741. #else
  742. #ifdef OS2
  743.     char c = getc(stdin);
  744. #else
  745.     char c = getch();
  746. #endif
  747. #endif
  748.  
  749.     if (c == 0) {
  750. #ifdef DJGPP
  751.     c = ch & 0xff;
  752. #else
  753. #ifdef OS2
  754.         c = getc(stdin);
  755. #else
  756.   c = getch(); /* Get the extended code. */
  757. #endif
  758. #endif
  759.     switch (c) {
  760.         case 75: /* Left Arrow. */
  761.         c = 002;
  762.         break;
  763.         case 77: /* Right Arrow. */
  764.         c = 006;
  765.         break;
  766.         case 72: /* Up Arrow. */
  767.         c = 020;
  768.         break;
  769.         case 80: /* Down Arrow. */
  770.         c = 016;
  771.         break;
  772.         case 115: /* Ctl Left Arrow. */
  773.         case 71: /* Home */
  774.         c = 001;
  775.         break;
  776.         case 116: /* Ctl Right Arrow. */
  777.         case 79: /* End */
  778.         c = 005;
  779.         break;
  780.         case 83: /* Delete */
  781.         c = 004;
  782.         break;
  783.         default:
  784.         c = 0;
  785.         break;
  786.     }
  787.     }
  788.     else if (c == 033) { /* ESC */
  789.     c = 025;
  790.     }
  791.  
  792.  
  793.     return c;
  794. }
  795.  
  796. #endif /* MSDOS */
  797.  
  798. #if defined(ATARI) || defined(MTOS)
  799.  
  800. /* Convert Arrow keystrokes to Control characters: TOS version */
  801.  
  802. long poll_events(int);        /* from term/atariaes.trm */
  803.  
  804. /* this function is used in help.c as well. this means that the
  805.    program doesn't work without -DREADLINE (which would be the case
  806.    if help.c didn't use it as well, since no events would be processed)
  807. */
  808.  
  809. char
  810. tos_getch()
  811. {
  812.     long rawkey;
  813.     char c;
  814.     int scan_code;
  815.     static int in_help = 0;
  816.  
  817.     if (strcmp(term->name,"atari") == 0) 
  818.         poll_events(0);
  819.  
  820.     if (in_help) {
  821.         switch(in_help) {
  822.             case 1:
  823.             case 5: in_help++; return 'e';
  824.             case 2:
  825.             case 6: in_help++; return 'l';
  826.             case 3:
  827.             case 7: in_help++; return 'p';
  828.             case 4: in_help = 0; return 0x0d;
  829.             case 8: in_help = 0; return ' ';
  830.         }
  831.     }
  832.  
  833.     if (strcmp(term->name,"atari") == 0) {
  834.         do {
  835.                if(Bconstat(2))
  836.                   rawkey = Cnecin();
  837.                else
  838.                   rawkey = poll_events(1);
  839.         } while(rawkey==0);
  840.     }
  841.     else
  842.         rawkey = Cnecin();
  843.  
  844.     c = (char)rawkey;
  845.     scan_code= ((int)(rawkey>>16)) & 0xff;    /* get the scancode */
  846.     if (Kbshift(-1) & 0x00000007) scan_code |= 0x80; /* shift or control ? */
  847.  
  848.     switch (scan_code) {
  849.     case 0x62:                /* HELP        */
  850.     case 0xe2:                /* shift HELP    */
  851.         if (max_pos==0) {
  852.             if (scan_code==0x62) {
  853.                 in_help = 1;
  854.             } else {
  855.                 in_help = 5;
  856.             }
  857.             return 'h';
  858.         } else {
  859.             return 0;
  860.         }
  861.     case 0x48: /* Up Arrow */
  862.         return 0x10; /* ^P */
  863.     case 0x50: /* Down Arrow */
  864.         return 0x0e; /* ^N */
  865.     case 0x4b: /* Left Arrow */
  866.         return 0x02; /* ^B */
  867.     case 0x4d: /* Right Arrow */
  868.         return 0x06; /* ^F */
  869.     case 0xcb: /* Shift Left Arrow */
  870.     case 0xf3: /* Ctrl Left Arrow (TOS-bug ?) */
  871.     case 0x47: /* Home */
  872.         return 0x01; /* ^A */
  873.     case 0xcd: /* Shift Right Arrow */
  874.     case 0xf4: /* Ctrl Right Arrow (TOS-bug ?) */
  875.     case 0xc7: /* Shift Home */
  876.     case 0xf7: /* Ctrl Home */
  877.         return 0x05; /* ^E */
  878.     case 0x61: /* Undo - redraw line */
  879.         return 0x0c; /* ^L */
  880.     default:
  881.         if (c == 0x1b) return 0x15; /* ESC becomes ^U */
  882.         if (c == 0x7f) return 0x04; /* Del becomes ^D */
  883.         break;
  884.     }
  885.     return c;
  886. }
  887.  
  888. #endif /* ATARI || MTOS */
  889.  
  890.   /* set termio so we can do our own input processing */
  891. static void
  892. set_termio()
  893. {
  894. #if !defined(MSDOS) && !defined(ATARI) && !defined(MTOS) && !defined(_Windows) && !defined(DOS386)
  895. /* set termio so we can do our own input processing */
  896. /* and save the old terminal modes so we can reset them later */
  897.     if(term_set == 0) {
  898.         /*
  899.          * Get terminal modes.
  900.          */
  901. #ifndef OSK
  902. #ifdef SGTTY
  903.         ioctl(0, TIOCGETP, &orig_termio);
  904. #else  /* SGTTY */
  905. #ifdef TERMIOS
  906. #ifdef TCGETS
  907.         ioctl(0, TCGETS, &orig_termio);
  908. #else
  909.         tcgetattr(0, &orig_termio);
  910. #endif /* TCGETS */
  911. #else
  912.         ioctl(0, TCGETA, &orig_termio);
  913. #endif /* TERMIOS */
  914. #endif /* SGTTY */
  915. #else  /* OSK */
  916.         setbuf(stdin, (char *)0);        /* Make stdin and stdout unbuffered */
  917.         setbuf(stderr, (char *)0);
  918.         _gs_opt (STDIN, &new_settings);
  919. #endif
  920.  
  921.         /*
  922.          * Save terminal modes
  923.          */
  924. #ifndef OSK
  925.         rl_termio = orig_termio;
  926. #else
  927.         _gs_opt (STDIN, &old_settings);
  928. #endif
  929.  
  930.         /*
  931.          * Set the modes to the way we want them
  932.          *  and save our input special characters
  933.          */
  934. #ifndef OSK
  935. #ifdef SGTTY
  936.         rl_termio.sg_flags |= CBREAK;
  937.         rl_termio.sg_flags &= ~(ECHO|XTABS);
  938.         ioctl(0, TIOCSETN, &rl_termio);
  939.  
  940.         ioctl(0, TIOCGETC, &s_tchars);
  941.         term_chars[VERASE]   = orig_termio.sg_erase;
  942.         term_chars[VEOF]     = s_tchars.t_eofc;
  943.         term_chars[VKILL]    = orig_termio.sg_kill;
  944. #ifdef TIOCGLTC
  945.         ioctl(0, TIOCGLTC, &s_ltchars);
  946.         term_chars[VWERASE]  = s_ltchars.t_werasc;
  947.         term_chars[VREPRINT] = s_ltchars.t_rprntc;
  948.         term_chars[VSUSP]    = s_ltchars.t_suspc;
  949.  
  950.         /* disable suspending process on ^Z */
  951.         s_ltchars.t_suspc = 0;
  952.         ioctl(0, TIOCSLTC, &s_ltchars);
  953. #endif /* TIOCGLTC */
  954. #else  /* SGTTY */
  955.         rl_termio.c_iflag &= ~(BRKINT|PARMRK|INPCK|IUCLC|IXON|IXOFF);
  956.         rl_termio.c_iflag |=  (IGNBRK|IGNPAR);
  957.  
  958.         /* rl_termio.c_oflag &= ~(ONOCR); Costas Sphocleous Irvine,CA */
  959.  
  960.         rl_termio.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|NOFLSH);
  961. #ifdef OS2
  962.  /* for emx: remove default terminal processing */
  963.                 rl_termio.c_lflag &= ~(IDEFAULT);
  964. #endif /* OS2 */
  965.         rl_termio.c_lflag |=  (ISIG);
  966.         rl_termio.c_cc[VMIN] = 1;
  967.         rl_termio.c_cc[VTIME] = 0;
  968.  
  969. #ifndef VWERASE
  970. #define VWERASE 3
  971. #endif
  972.         term_chars[VERASE]   = orig_termio.c_cc[VERASE];
  973.         term_chars[VEOF]     = orig_termio.c_cc[VEOF];
  974.         term_chars[VKILL]    = orig_termio.c_cc[VKILL];
  975. #ifdef TERMIOS
  976.         term_chars[VWERASE]  = orig_termio.c_cc[VWERASE];
  977. #ifdef VREPRINT
  978.         term_chars[VREPRINT] = orig_termio.c_cc[VREPRINT];
  979. #else
  980. #ifdef VRPRNT
  981.         term_chars[VRPRNT] = orig_termio.c_cc[VRPRNT];
  982. #endif
  983. #endif
  984.         term_chars[VSUSP]    = orig_termio.c_cc[VSUSP];
  985.  
  986.         /* disable suspending process on ^Z */
  987.         rl_termio.c_cc[VSUSP] = 0;
  988. #endif /* TERMIOS */
  989. #endif /* SGTTY */
  990. #else  /* OSK */
  991.         new_settings._sgs_echo = 0;        /* switch off terminal echo */
  992.         new_settings._sgs_pause = 0;    /* inhibit page pause */
  993.         new_settings._sgs_eofch = 0;    /* inhibit eof    */
  994.         new_settings._sgs_kbich = 0;    /* inhibit ^C    */
  995.         new_settings._sgs_kbach = 0;    /* inhibit ^E    */
  996. #endif
  997.  
  998.         /*
  999.          * Set the new terminal modes.
  1000.          */
  1001. #ifndef OSK
  1002. #ifdef SGTTY
  1003.         ioctl(0, TIOCSLTC, &s_ltchars);
  1004. #else
  1005. #ifdef TERMIOS
  1006. #ifdef TCSETSW
  1007.         ioctl(0, TCSETSW, &rl_termio);
  1008. #else
  1009.         tcsetattr(0, TCSADRAIN, &rl_termio);
  1010. #endif /* TCSETSW */
  1011. #else
  1012.         ioctl(0, TCSETAW, &rl_termio);
  1013. #endif /* TERMIOS */
  1014. #endif /* SGTTY */
  1015. #else  /* OSK */
  1016.         _ss_opt (STDIN, &new_settings);
  1017. #endif
  1018.         term_set = 1;
  1019.     }
  1020. #endif /* !MSDOS && !ATARI && !MTOS && !defined(_Windows) */
  1021. }
  1022.   
  1023. static void
  1024. reset_termio()
  1025. {
  1026. #if !defined(MSDOS) && !defined(ATARI) && !defined(MTOS) && !defined(_Windows) && !defined(DOS386)
  1027. /* reset saved terminal modes */
  1028.     if(term_set == 1) {
  1029. #ifndef OSK
  1030. #ifdef SGTTY
  1031.         ioctl(0, TIOCSETN, &orig_termio);
  1032. #ifdef TIOCGLTC
  1033.         /* enable suspending process on ^Z */
  1034.         s_ltchars.t_suspc = term_chars[VSUSP];
  1035.         ioctl(0, TIOCSLTC, &s_ltchars);
  1036. #endif /* TIOCGLTC */
  1037. #else  /* SGTTY */
  1038. #ifdef TERMIOS
  1039. #ifdef TCSETSW
  1040.         ioctl(0, TCSETSW, &orig_termio);
  1041. #else
  1042.         tcsetattr(0, TCSADRAIN, &orig_termio);
  1043. #endif /* TCSETSW */
  1044. #else
  1045.         ioctl(0, TCSETAW, &orig_termio);
  1046. #endif /* TERMIOS */
  1047. #endif /* SGTTY */
  1048. #else  /* OSK */
  1049.         _ss_opt (STDIN, &old_settings);
  1050. #endif
  1051.         term_set = 0;
  1052.     }
  1053. #endif /* !MSDOS && !ATARI && !MTOS && !_Windows */
  1054. }
  1055. #endif /* READLINE */
  1056.